<template>
  <header class="header">
    <h2>filebeat检测面板</h2>
  </header>
  <div class="statistics-box">
    <div class="statistics">
      <a-statistic title="实例数量" :value="filebeatInstances.length" :precision="0" :value-from="0" :start="true">
        <template #prefix>
          <icon-arrow-rise />
        </template>
      </a-statistic>
      <a-statistic
        title="正常数量"
        :value="filebeatInstances.length - errorIPs.length"
        :precision="0"
        :value-from="0"
        :start="true"
        :value-style="{ color: '#0fbf60' }"
      >
        <template #prefix>
          <icon-arrow-rise />
        </template>
      </a-statistic>
      <a-statistic
        title="异常数量"
        :value="errorIPs.length"
        :precision="0"
        :value-from="0"
        :start="true"
        :value-style="{ color: '#f5222d' }"
      >
        <template #prefix>
          <icon-arrow-rise />
        </template>
      </a-statistic>
    </div>
    <div class="statistics-error-ips">
      <template v-if="errorIPs.length">
        <a-tag v-for="ip in errorIPs" :key="ip" class="error-ip" color="red">
            {{ ip }}
        </a-tag>
      </template>
      <template v-else>
        <a-empty>
          <template #image>
            <icon-face-smile-fill />
          </template>
          没有异常IP
        </a-empty>
      </template>
    </div>
  </div>
  <div class="container">
    <a-space direction="vertical" fill>
      <a-input v-model="searchIP" :style="{width:'320px'}" placeholder="输入ip搜索过滤" :size="size" allow-clear />
      <a-table :columns="fileBeatInstanceColumns" :data="filterFilebeatInstances" :pagination="false" :virtual-list-props="{ height: 400 }">
        <template  #ip="{ record }">
          <a-typography>
            <a-typography-paragraph copyable>
              {{ record.ip }}
            </a-typography-paragraph>
          </a-typography>
        </template>
        <template #status="{ record }">
          <span
            :style="{
              color: record.status === '异常' ? '#f5222d' : '#52c41a'
            }"
            >{{ record.status }}</span
          >
        </template>
        <template #systemCpuLoad="{ record }">
          <span
            :style="{
              color: record.systemCpuLoad > '70.00%' ? '#f5222d' : '#52c41a'
            }"
            >{{ record.systemCpuLoad }}</span
          >
        </template>
        <template #time="{ record }">
          <template v-if="loadingMap[record.ip]">
            <a-spin :size="14" />
          </template>
          <template v-else>{{ new Date(record.time).toLocaleString() }}</template>
        </template>
      </a-table>
    </a-space>
  </div>
</template>

<script setup>
import { onMounted, reactive, computed, ref } from "vue";
import { loadIPs, getFileBeatData } from "@/api/filebeat";
import { FileBeatInstance, chunkArray } from "@/util/index";
import { fileBeatInstanceColumns } from "@/const/filebeatInstance";
import { IconFaceSmileFill } from "@arco-design/web-vue/es/icon";

const size = "small";
const filebeatInstances = reactive([]);
const loadingMap = reactive({});
const searchIP = ref("");
const rotationInterval = 10 * 1000;

const filterFilebeatInstances = computed(() => filebeatInstances.filter(item => item.ip.includes(searchIP.value)));

const errorIPs = computed(() => filebeatInstances.filter(item => item.status === "异常").map(item => item.ip));

const initData = async (ip, filebeatInstance) => {
  loadingMap[ip] = true;
  return new Promise(resolve => {
    getFileBeatData(ip).then(({ data }) => {
      if (filebeatInstance) {
        filebeatInstance.setData(data || {})
      } else {
        const filebeat = new FileBeatInstance(ip, data || {});
        filebeatInstances.push(filebeat);
      }
    }).finally(() => {
      loadingMap[ip] = false;
      resolve();
    })
  });
}

onMounted(async () => {
  const ips = await loadIPs();
  const ipsChunks = chunkArray(ips, 6);
  for (const ipsChunk of ipsChunks) {
    await Promise.all(ipsChunk.map(ip => initData(ip)))
  }
  setInterval(() => {
    update();
  }, rotationInterval);
});
async function update() {
  const interval = 1000 * 9;
  const day = 1000 * 60 * 60 * 24;
  const updateFilebeatInstances = filebeatInstances.filter(filebeatInstance => new Date().getTime() - new Date(filebeatInstance.time).getTime() > interval);
  const updateFilebeatInstancesChunks = chunkArray(updateFilebeatInstances, 8);
  for (const updateFilebeatInstancesChunk of updateFilebeatInstancesChunks) {
    await Promise.all(updateFilebeatInstancesChunk.map(filebeatInstance => initData(filebeatInstance.ip, filebeatInstance)))
  }
}
</script>
<style scoped>
.header {
  background-color: #fff;
  box-shadow: var(--shadow);
  padding: 16px 5%;
  color: #1664ff;
}
.container {
  padding: 16px;
  background-color: #fff;
  margin: 16px 5%;
  box-shadow: var(--shadow);
}
.statistics-box {
  display: flex;
  margin: 16px 5%;
}
.statistics {
  display: flex;
  justify-content: space-between;
  width: 400px;
  box-shadow: var(--shadow);
  padding: 24px;
  background-color: #fff;
}
.statistics-error-ips {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  margin-left: 16px;
  box-shadow: var(--shadow);
  padding: 24px;
  background-color: #fff;
  gap: 8px;
}
</style>
